package com.manage.company.kotlin

import android.animation.Animator
import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.animation.LinearInterpolator
import com.example.timeseletor.R
import kotlin.math.abs
import kotlin.math.min

/**
 * @Author: whz
 * @Description: 数字选择器 监听数字滚动事件
 * @Date: create in 2021/4/26 14:43
 */
class DateSelector:View {
    // 需要拼接的文本 如 2021+年
    private var mText: String = ""

    //    选中数字的颜色
    private var checkedTextColor = Color.BLACK

    //    未选中数字的颜色
    private var textColor = Color.BLACK

    //    划线颜色
    private var lineColor = Color.BLACK

    //   显示的最大值
    private var maxValue: Int = 10

    //    显示的最小值
    private var minValue: Int = 0

    //    是否显示文字
    private var isShowText: Boolean = true

    //    高
    private var mHeight: Int? = null

    //    宽
    private var mWidth: Int? = null

    //二分之一高
    private var middleHeight: Int? = null

    //二分之一宽
    private var middleWidht: Int? = null

    //单位高度
    private var mUnitHeight: Int? = 0

    //数据
    private var mData: ArrayList<String> = ArrayList()

    //当前位置
    private var mCurrentPostion = 0;

    //偏移量
    private var pivot: Float? = 0f

    //画笔
    private var mPaint: Paint? = null

    //字体的矩形
    private var mRect: Rect? = null

    //落点Y
    private var downY: Float? = null

    //缩放扩大比例
    private var mScale: Float? = 1f

    //滚轮状态
    private var mStatus: Status? = Status.IDEL

    //遮罩效果
    private var mLg: LinearGradient? = null

    //数值估值器
    private var mValueAnimator: ValueAnimator? = null

    //字体大小
    private var textSize: Int? = null

    //字体大小差
    private var textStep: Int? = 5

    //显示个数
    private var mShowNum: Int? = 5

    //字体颜色
//    private var mTextColor = Color.parseColor(DEF_TEXT_COLOR);

    //选择监听
    private var mListener: OnSelectNumListener? = null

    //颜色渐变计算器
    private var mArgvEvlauator: ArgbEvaluator? = null

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attributeSet: AttributeSet? = null) : this(
        context,
        attributeSet,
        0
    )

    constructor(context: Context, attributeSet: AttributeSet? = null, defStyleAttr: Int) : super(
        context,
        attributeSet,
        defStyleAttr
    ) {
        val ta = context.obtainStyledAttributes(attributeSet, R.styleable.TimeSelectorView)
        for (i in 0 until ta.indexCount) {
            var index = ta.getIndex(i)
            when (index) {
                R.styleable.TimeSelectorView_isShowText -> {
                    isShowText = ta.getBoolean(index, isShowText)
                    if (!isShowText) {
                        mText = ""
                    }
                }
                R.styleable.TimeSelectorView_disText -> {
                    mText = ta.getString(R.styleable.TimeSelectorView_disText).toString()
                }
                R.styleable.TimeSelectorView_maxValue, R.styleable.TimeSelectorView_minValue -> {
                    maxValue = ta.getInt(R.styleable.TimeSelectorView_maxValue, 10)
                    minValue = ta.getInt(R.styleable.TimeSelectorView_minValue, 0)
                    for (i2 in minValue until maxValue) {
                        if (i2 < 10) {
                            mData.add("0" + i2 + mText)
                        } else {
                            mData.add(i2.toString() + mText)
                        }
                    }
                }
                R.styleable.TimeSelectorView_showNum -> {
                    mShowNum = ta.getInt(index, 6)
                }
                R.styleable.TimeSelectorView_nowNum -> {
                    mCurrentPostion = ta.getInt(index, 0)
                }
                R.styleable.TimeSelectorView_textColor, R.styleable.TimeSelectorView_checkedTextColor, R.styleable.TimeSelectorView_lineColor -> {
                    textColor = ta.getColor(R.styleable.TimeSelectorView_textColor, textColor)
                    checkedTextColor=ta.getColor(R.styleable.TimeSelectorView_checkedTextColor,checkedTextColor)
                    lineColor=ta.getColor(R.styleable.TimeSelectorView_lineColor,lineColor)
                }
            }
        }
        ta.recycle()
        init()
    }

    private fun init() {
        mPaint = Paint()
        mPaint!!.isAntiAlias = true
        mPaint!!.textAlign = Paint.Align.CENTER
        mRect = Rect()
        mArgvEvlauator = ArgbEvaluator()
        mValueAnimator = ValueAnimator()
        mValueAnimator!!.apply {
            setDuration(300)
            mValueAnimator!!.interpolator = LinearInterpolator()
            addUpdateListener {
                var value: Float = it.animatedValue as Float
                if (abs(pivot!!) > mUnitHeight!!) {
                    return@addUpdateListener
                }
                pivot = value
                mScale = min(1f, abs(pivot!! / mUnitHeight!!))
                invalidate()
            }

        }
        mValueAnimator!!.addListener(object : Animator.AnimatorListener {
            override fun onAnimationRepeat(animation: Animator?) {

            }

            override fun onAnimationEnd(animation: Animator?) {
                if (mStatus == Status.UP && pivot!!.toInt() != 0) {
                    mCurrentPostion = clamp(mCurrentPostion + 1)
                } else if (mStatus == Status.DOWN && pivot!!.toInt() != 0) {
                    mCurrentPostion = clamp(mCurrentPostion - 1)
                }
                invalidate()
                pivot = 0f
                mStatus = Status.IDEL
                mScale = 0f
                if (mListener != null) {
                    mListener!!.onSelected(mCurrentPostion+minValue)
                }
            }

            override fun onAnimationCancel(animation: Animator?) {

            }


            override fun onAnimationStart(animation: Animator?) {

            }

        })
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        mHeight = measuredHeight
        mWidth = measuredWidth
        middleHeight = mHeight!! / 2
        middleWidht = mWidth!! / 2
        mUnitHeight = (mHeight!! - paddingTop + paddingBottom) / mShowNum!!
        textSize = mUnitHeight!! / 2
        mUnitHeight = (mHeight!! - paddingTop + paddingBottom) / mShowNum!!
        textSize = mUnitHeight!! / 2
        textStep = mUnitHeight!! / 9
    }

    override fun onDrawForeground(canvas: Canvas?) {
        super.onDrawForeground(canvas)
//        画选中字体
        drawText(canvas, mData.get(mCurrentPostion), 0, 1)
//        画除中间外上下字体
//        var num = mShowNum!! / 2
        for (i in 0 until mShowNum!!) {
            drawText(canvas, mData.get(clamp(mCurrentPostion + i)), i, 1)
            if ((mCurrentPostion-minValue)<mShowNum!!/2){
                for (i in 0 until mCurrentPostion-minValue){
                    drawText(canvas, mData.get(clamp(mCurrentPostion - i)), i, -1)
                }
            }else{
                drawText(canvas, mData.get(clamp(mCurrentPostion - i)), i, -1)
            }
        }
    }

    fun setNowNum(num: Int){
        mCurrentPostion=num-minValue
        invalidate()
    }

    //设置默认值 2021年    拼接的文字 是否显示文字 显示的最大数值 显示的最小数值
    fun setDefaultAttribute(text: String, isShowText: Boolean, maxValue: Int, minValue: Int) {
        if (maxValue < minValue) {
            throw IllegalArgumentException("数字最大值必须大于最小值")
        } else {
            this.maxValue = maxValue
            this.minValue = minValue
            mText = text
            if (!isShowText) {
                mText = ""
            }
            mData.clear()
            for (i2 in minValue until maxValue) {
                if (i2 < 10) {
                    mData.add("0" + i2 + " " + mText)
                } else {
                    mData.add(i2.toString() + " " + mText)
                }
            }
            invalidate()
        }

    }


    /**
     * 选中当前数值
     */
    fun select(num: Int) {
        if (num < 0 || num >= mData.size) {
            throw IllegalArgumentException("数字必须在0到${mData.size - 1}之间")
        }
        mCurrentPostion = num
        if (mListener != null) {
            mListener!!.onSelected(mCurrentPostion)
        }
    }

    /**
     * level 选中为0级，每差一个index 加一级
     */
    fun drawText(canvas: Canvas?, text: String, level: Int, direct: Int) {
        mPaint!!.reset()
        mPaint!!.setShader(null)
//        字的位置渐变量
        var offset = direct * level * mUnitHeight!!
//        字体的大小变化
        var step = (direct * Status.getValue() * mScale!! * textStep!!)

        if (level == 0) {
//            中间字体无论怎么样都是缩小的
            mPaint!!.setColor(checkedTextColor)
//            mPaint!!.textSize = textSize!! - abs(step)
            mPaint!!.textSize = (mUnitHeight!! / 3).toFloat()
            mPaint!!.getTextBounds(text, 0, text.length, mRect)


            canvas!!.drawText(
                text,
                (middleWidht!! - mRect!!.width() / 2).toFloat() + 60f,
                mHeight!! / 2 + mRect!!.height() / 2 + pivot!!,
                mPaint!!
            )

            mPaint!!.setColor(lineColor)
            canvas.drawLine(
                0f,
                350f,
                500f,
                350f,
                mPaint!!
            )

            canvas.drawLine(
                0f,
                450f,
                500f,
                450f,
                mPaint!!
            )

        } else {
//            其它字体根据上下和滑动方向关系放大或缩小，颜色渐变
            var color = mArgvEvlauator!!.evaluate(
                1 - abs(mRect!!.height() / 2 + offset + pivot!!) / middleHeight!!,
                textColor,
                textColor
            ) as Int
            mPaint!!.setColor(color)
//            mPaint!!.textSize = textSize!! - abs(step)
            mPaint!!.textSize = (mUnitHeight!! / 3).toFloat()
            mPaint!!.getTextBounds(text, 0, text.length, mRect)
            canvas!!.drawText(
                text,
                (middleWidht!! - mRect!!.width() / 2).toFloat() + 60f,
                middleHeight!! + mRect!!.height() / 2 + offset + pivot!!,
                mPaint!!
            )

        }
        invalidate()
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when (event!!.action) {
            MotionEvent.ACTION_DOWN -> {
                downY = event.getY()
                mValueAnimator!!.cancel()
            }
            MotionEvent.ACTION_MOVE -> {
                pivot = event.getY() - downY!!
                if (pivot!! > 0) {
//                    向下
                    mStatus = Status.DOWN
                    if (abs(pivot!!) > mUnitHeight!!) {
                        mCurrentPostion = clamp(mCurrentPostion - 1)
                        downY = event.getY()
                        pivot = 0f
                    } else {
                        invalidate()
                    }
                } else {
                    //向上
                    mStatus = Status.UP
                    if (abs(pivot!!) > mUnitHeight!!) {
                        mCurrentPostion = clamp(mCurrentPostion + 1)
                        downY = event.getY()
                        pivot = 0f
                    } else {
                        invalidate()
                    }
                }
                mScale = min(1f, abs(pivot!! / mUnitHeight!!))
            }
            MotionEvent.ACTION_CANCEL -> {
            }
            MotionEvent.ACTION_UP -> {
                if (pivot!!.toInt() == 0) {
//                    把点击事件统一为滑动事件处理，简化流程
                    pivot = 0.00001f
                }
                if (abs(pivot!!) > mUnitHeight!! / 2) {
//                    需要过度
                    var rest = abs(mUnitHeight!! / 2 - pivot!!)
                    if (mStatus == Status.UP) {
                        mValueAnimator!!.setFloatValues(pivot!!, -rest)
                    } else if (mStatus == Status.DOWN) {
//
                        mValueAnimator!!.setFloatValues(pivot!!, pivot!! + rest + mUnitHeight!! / 2)
                    }
                } else {
//                    过度失败，返回值，所以终点都是0
                    if (mStatus == Status.UP) {
                        mValueAnimator!!.setFloatValues(pivot!!, 0f)
                    } else if (mStatus == Status.DOWN) {
                        mValueAnimator!!.setFloatValues(pivot!!, 0f)
                    }
                }
                if (mValueAnimator!!.values == null || mValueAnimator!!.values.size == 0) {
                    return false
                }
                mValueAnimator!!.start()
            }
        }

        return true
    }

    fun getCurrentPosition(): Int {
        return mCurrentPostion
    }

    /**
     * 保证 index 合法化
     *
     * @param p 下标
     * @return 合法后的下标
     */
    fun clamp(p: Int): Int {
        if (p > mData.size - 1) {
            return p - mData.size
        } else if (p < 0) {
            return mData.size - abs(p)
        }
        return p
    }

    /**
     * 滚轮状态
     */
    enum class Status(var value: Int) {
        UP(1), DOWN(-1), IDEL(0);

        companion object {
            fun getValue(): Int {
                return Status.UP.value
            }
        }
    }

    /**
     * 设置滚轮监听
     */
    fun setOnSelectNumListener(listener: OnSelectNumListener) {
        this.mListener = listener
    }

    /**
     * 监听接口
     */
    interface OnSelectNumListener {
        fun onSelected(num: Int)
    }

}